#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <openssl/md5.h>
#include <glib.h>
#include <dlfcn.h>
#include <time.h>

#include "type.h"

#include "dict.h"
#include "date.h"
#include "encrypt.h"
#include "misc.h"
#include "kylin-activation.h"
#include "kylin-license.h"
#include "kylin-verify.h"


/*
 * kylin_get_license, get license information in vikey
 *   ukey_license_keyfile - LICENSE文件
 *   data - LICENSE 数据的首地址
 * return NO_ERROR if succeed, or error number if not
 */
int kylin_get_license(GKeyFile** ukey_license_keyfile, const char *data)
{
	gboolean res;
	//DWORD ret;
	GKeyFileFlags flags;
	GError* error = NULL;
	GKeyFile* keyfile = NULL;

	if(*ukey_license_keyfile)
		return NO_ERROR;
	
	/*
	
	ret = vikey_get_data_force();
	if(ret != NO_ERROR)
		return ret;
	*/

	keyfile = g_key_file_new();
	if(!keyfile)
		return UKEY_KEY_FILE_ERROR;

	flags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS;

	// res = g_key_file_load_from_data(ukey_license_keyfile, (const char*)&vikey_data[ADMIN_SPACE_OFFSET], strlen((const char*)&vikey_data[ADMIN_SPACE_OFFSET]), flags, &error);
	res = g_key_file_load_from_data(keyfile, data, strlen(data), flags, &error);
	if(!res)
	{
		g_key_file_free(keyfile);
		*ukey_license_keyfile = NULL;

		return UKEY_KEY_FILE_ERROR;
	}

	*ukey_license_keyfile = keyfile;
	return NO_ERROR;
}


/*
 * kylin_get_license_value, get license information by key in Usb Key
 * key: key string
 * return value string if succeed, or NULL if not
 */
char* kylin_get_license_value(GKeyFile* ukey_license_keyfile, const char *data, char* key)
{
	DWORD ret;
	char* value = NULL;

	if(!ukey_license_keyfile)
	{
		ret = kylin_get_license(&ukey_license_keyfile, data);
		if(ret != NO_ERROR)
			return NULL;
	}

	value = key_file_get_value(ukey_license_keyfile, LICENSE_GROUP, key);
	if(!value || strcmp(value, "None") ==0)
		value = NULL;

	return value;
}

/*
 * kylin_get_license_serial, get serial string in license information
 * return value string if succeed, or NULL if not
 */
char* kylin_get_license_serial(GKeyFile* ukey_license_keyfile, const char *data)
{
	return kylin_get_license_value(ukey_license_keyfile, data, "serial");
}

/*
 * kylin_get_license_expire, get expire date string in license information
 * return value string if succeed, or NULL if not
 */
char* kylin_get_license_expire(GKeyFile* ukey_license_keyfile, const char *data)
{
	return kylin_get_license_value(ukey_license_keyfile, data, "term");
}

/*
 * kylin_get_license_to, get destination string in license information
 * return value string if succeed, or NULL if not
 */
char* kylin_get_license_to(GKeyFile* ukey_license_keyfile, const char *data)
{
	return kylin_get_license_value(ukey_license_keyfile, data, "to");
}

/*
 * kylin_get_license_produce, get produce string in license information
 * return value string if succeed, or NULL if not
 */
char* kylin_get_license_produce(GKeyFile* ukey_license_keyfile, const char *data)
{
	return kylin_get_license_value(ukey_license_keyfile, data, "produce");
}

/*
 * kylin_get_license_count, get count value in license information
 */
int kylin_get_license_count(GKeyFile* ukey_license_keyfile, const char *data)
{
    char* value = NULL;
    int count = 0;

    value = kylin_get_license_value(ukey_license_keyfile, data, "count");
    if (value) {
        count = atoi(value);
    }

    return count;
}

/*int kylin_get_license_count(GKeyFile* ukey_license_keyfile, char *data)
{
	char* count_str = NULL;
	int count = 0;

	count_str = kylin_get_license_value(ukey_license_keyfile, data, "count");
	if(!count_str)
		return 0;

	count = atoi(count_str);
	if(count > 0)
		return count;

	return 0;
}
*/





/*
 * kylin_find_register_code, search for register code in vikey
 * return 1 if found, or 0 if not
 */
int kylin_find_register_code(const char* register_code, const char* buf, size_t size)
{
	int _index = 0;
	int count = 0;

	count = size - (size % SPACE_ALIGNMENT);

	for(_index = 0; _index < count; _index += ENCRYPTED_NUMBER_LENGTH)
	{
		if(strncmp(register_code, &buf[_index], ENCRYPTED_NUMBER_LENGTH) == 0)
			return 1;
	}

	return 0;
}

/*
 * kylin_check_register_code_space_validation, try to find a empty place in vikey for register code
 * return the first index of empty place in vikey
 */
int kylin_check_register_code_space_validation(const char* buf, const size_t size)
{
	int _index = 0;
	int count = 0;
	char register_code[ENCRYPTED_NUMBER_LENGTH + 1];

	count = size - (size % SPACE_ALIGNMENT);
	register_code[ENCRYPTED_NUMBER_LENGTH] = '\0';

	for(_index = 0; _index < count; _index += ENCRYPTED_NUMBER_LENGTH)
	{
		memcpy(register_code, &buf[_index], ENCRYPTED_NUMBER_LENGTH);
		if(!register_code_is_valid(register_code))
			break;
	}

	return _index;
}

